package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.AlbumTrackListVo;
import com.atguigu.tingshu.vo.album.TrackInfoVo;
import com.atguigu.tingshu.vo.album.TrackListVo;
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;
    @Autowired
    private AlbumInfoMapper albumInfoMapper;
    @Autowired
    private VodService vodService;
    @Autowired
    private TrackStatMapper trackStatMapper;
    @Autowired
    private AlbumInfoService albumInfoService;
    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
        try {
            // 创建声音对象
            TrackInfo trackInfo = new TrackInfo();
            // 属性拷贝
            BeanUtils.copyProperties(trackInfoVo, trackInfo);
            //	赋值用户Id
            trackInfo.setUserId(userId);
            trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
            //	order_num; 第一种查询当前专辑对应的声音集数+1; 第二种：查询专辑包含声音总数+1;
            AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
            trackInfo.setOrderNum(albumInfo.getIncludeTrackCount() + 1);
//	处理流媒体的数据; 时长，类型这些数据页面没有传递；fileId 查询流媒体数据，然后赋值：调用云点播的api;
            TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
            //	赋值：
            trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
            trackInfo.setMediaType(trackMediaInfoVo.getType());
            trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
            trackInfo.setMediaSize(trackMediaInfoVo.getSize());
            //	保存声音结束;
            trackInfoMapper.insert(trackInfo);
            //track_stat
            saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
            saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
            saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
            saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);
            //	album_info; 更新数据;
            albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
            //	更新操作;
            albumInfoMapper.updateById(albumInfo);
        } catch (BeansException e) {
            log.error("保存声音信息失败：{}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 保存声音统计数据
     *
     * @param trackId
     * @param statPlay
     */
    public void saveTrackStat(Long id, String trackStatPraise) {
        TrackStat trackStat = new TrackStat();
        //	赋值
        trackStat.setTrackId(id);
        trackStat.setStatType(trackStatPraise);
        trackStat.setStatNum(new Random().nextInt(10000));
        //	数据保存
        trackStatMapper.insert(trackStat);
    }


    @Override
    public IPage<TrackListVo> findUserTrackPage(Page<TrackListVo> trackInfoPage, TrackInfoQuery trackInfoQuery) {
        //调用mapper层方法
        return trackInfoMapper.selectUserTrackPage(trackInfoPage, trackInfoQuery);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeTrackInfo(Long id) {
        // 获取声音对象数据
        TrackInfo trackInfo = trackInfoMapper.selectById(id);
        // 删除
        trackInfoMapper.deleteById(id);
        //更新专辑声音总数
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
        albumInfoMapper.updateById(albumInfo);
        //删除统计数据
        trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, id));
        //  序号重新更新
        trackInfoMapper.updateTrackNum(trackInfo.getAlbumId(), trackInfo.getOrderNum());
        //删除声音媒体
        vodService.removeTrack(trackInfo.getMediaFileId());
    }

    @Override
    public void updateTrackInfo(Long id, TrackInfoVo trackInfoVo) {
        //	获取到声音对象
        TrackInfo trackInfo = trackInfoMapper.selectById(id);
        //    获取传递的fileId
        String mediaFileId = trackInfo.getMediaFileId();
        //	进行属性拷贝
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //	获取声音信息 页面传递的fileId 与 数据库的 fileId 不相等就修改
        if (!mediaFileId.equals(trackInfoVo.getMediaFileId())) {
            //	说明已经修改过了.
            TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
            //	判断对象不为空.
            if (null == mediaInfo) {
                //	抛出异常
                throw new GuiguException(ResultCodeEnum.VOD_FILE_ID_ERROR);
            }
            trackInfo.setMediaUrl(mediaInfo.getMediaUrl());
            trackInfo.setMediaType(mediaInfo.getType());
            trackInfo.setMediaDuration(mediaInfo.getDuration());
            trackInfo.setMediaSize(mediaInfo.getSize());
            // 删除云点播声音
            vodService.removeTrack(mediaFileId);
        }
        //	修改数据
        this.updateById(trackInfo);
    }

    @Override
    public IPage<AlbumTrackListVo> findAlbumTrackPage(IPage<AlbumTrackListVo> iPage, Long albumId, Long userId) {
        //	根据专辑Id 获取到声音集合
        IPage<AlbumTrackListVo> pageInfo = trackInfoMapper.selectAlbumTrackPage(iPage, albumId);

        //	判断用户是否需要付费：0101-免费 0102-vip付费 0103-付费
        AlbumInfo albumInfo = albumInfoService.getAlbumInfoById(albumId);
        Assert.notNull(albumInfo, "专辑信息不存在！");
        //判断用户是否登录
        if (null == userId) {
            //除免费的专辑都需要显示付费表示
            if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())) {
                //处理试听声音，获取需要付费的声音列表
                List<AlbumTrackListVo> albumTrackNeedPaidListVoList = pageInfo.getRecords().stream()
                        .filter(albumTrackListVo ->
                                albumTrackListVo.getOrderNum() != null &&
                                        albumInfo.getTracksForFree() != null &&
                                        albumTrackListVo.getOrderNum().intValue() > albumInfo.getTracksForFree())
                        .collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(albumTrackNeedPaidListVoList)) {
                    albumTrackNeedPaidListVoList.forEach(albumTrackListVo -> {
                        //显示付费通知
                        albumTrackListVo.setIsShowPaidMark(true);
                    });
                }
            }
        } else {
            //用户登录了
            //声明变量是否需要付费，默认不需要付费
            boolean isNeedPaid = false;
            //vip付费情况
            if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())) {
                //获取用户信息
                Result<UserInfo> userInfoVoResult = userInfoFeignClient.getUserInfo(userId);
                Assert.notNull(userInfoVoResult, "用户信息不存在！");
                UserInfo userInfo = userInfoVoResult.getData();
                Assert.notNull(userInfo, "用户信息不存在！");
                UserInfoVo userInfoVo = new UserInfoVo();
                BeanUtils.copyProperties(userInfo, userInfoVo);
                //1.	VIP 免费,如果不是vip则需要付费，将这个变量设置为true，需要购买
                if (userInfoVo.getIsVip().intValue() == 0) {
                    isNeedPaid = true;
                }
                //1.1 如果是vip但是vip过期了（定时任务还为更新状态）
                if (userInfoVo.getIsVip().intValue() == 1 && userInfoVo.getVipExpireTime().before(new Date())) {
                    isNeedPaid = true;
                }
            } else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
                //付费
                isNeedPaid = true;
            }
            //需要付费，判断用户是否购买过专辑或声音
            if (isNeedPaid) {
                //处理试听声音，获取需要付费的声音列表
                List<AlbumTrackListVo> albumTrackNeedPaidListVoList = pageInfo.getRecords().stream().filter(albumTrackListVo ->
                        albumTrackListVo.getOrderNum().intValue()
                                > albumInfo.getTracksForFree()).collect(Collectors.toList());
                //判断
                if (!CollectionUtils.isEmpty(albumTrackNeedPaidListVoList)) {
                    //	判断用户是否购买该声音
                    //	获取到声音Id 集合列表
                    List<Long> trackIdList = albumTrackNeedPaidListVoList.stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());
                    //	获取用户购买的声音列表
                    Result<Map<Long, Integer>> mapResult = userInfoFeignClient.uderIsPaidTrack(albumId, trackIdList);
                    Assert.notNull(mapResult, "声音集合不能为空！");
                    Map<Long, Integer> map = mapResult.getData();
                    Assert.notNull(map, "map集合不能为空！");
                    albumTrackNeedPaidListVoList.forEach(albumTrackListVo -> {
                        //	如果map.get(albumTrackListVo.getTrackId()) == 1 已经购买过，则不显示付费标识;
                        boolean isBuy = map.get(albumTrackListVo.getTrackId()) == 1 ? false : true;
                        albumTrackListVo.setIsShowPaidMark(isBuy);
                    });
                }
            }
        }
        return pageInfo;
    }

    @Transactional
    @Override
    public void updateStat(Long albumId, Long trackId, String statType, Integer count) {
        //  1.  更新声音的播放量： update track_stat set stat_num = stat_num+1 where track_id = ? and stat_type = '0701' and is_deleted = 0;
        //  判断是否是属于播放量：
        if (SystemConstant.TRACK_STAT_PLAY.equals(statType)){
            //  调用更新方法;
            trackInfoMapper.updateTrackStat(trackId, statType, count);
            //  2.  更新专辑播放量；
            albumInfoMapper.updateAlbumStat(albumId, SystemConstant.ALBUM_STAT_PLAY, count);
        }
    }

    @Override
    public List<Map<String, Object>> findUserTrackPaidList(Long trackId) {
        //获取声音对象
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        //获取专辑对象
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        //根据专辑Id 获取到用户已购买的声音Id集合
        Result<List<Long>> trackIdListResult =userInfoFeignClient.findUserPaidTrackIdList(albumInfo.getId());
        Assert.notNull(trackIdListResult, "专辑Id集合不为空！");
        List<Long> trackIdList = trackIdListResult.getData();
        Assert.notNull(trackIdList, "声音专辑Id不为空！");

        // 获取当前专辑并且大于当前声音的全部声音Id
        List<TrackInfo> trackInfos = trackInfoMapper.selectList(new LambdaQueryWrapper<TrackInfo>()
                .eq(TrackInfo::getAlbumId, albumInfo.getId())
                .gt(TrackInfo::getOrderNum, trackInfo.getOrderNum())
                .select(TrackInfo::getId));
        List<Long> trackIdAllList = trackInfos.stream().map(TrackInfo::getId).collect(Collectors.toList());
        //去除已支付的
        List<Long> payIdList = trackIdAllList.stream()
                .filter(itemId -> !trackIdList.contains(itemId)).collect(Collectors.toList());

        // 构造声音分集购买数据列表
        List<Map<String, Object>> list=new ArrayList<>();
        //需要付款的集数有
        //本集
        if(payIdList.size() >= 0) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", "本集");
            map.put("price", albumInfo.getPrice());
            map.put("trackCount", 0);
            list.add(map);
        }

        //后10集
        if(payIdList.size() > 0 && payIdList.size() <= 10) {
            Map<String, Object> map = new HashMap<>();
            int count = payIdList.size();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
            map.put("name", "后"+payIdList.size()+"集");
            map.put("price", price);
            map.put("trackCount", count);
            list.add(map);
        }
        // 19
        if(payIdList.size() > 10) {
            Map<String, Object> map = new HashMap<>();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(10));
            map.put("name", "后10集");
            map.put("price", price);
            map.put("trackCount", 10);
            list.add(map);
        }
        // 后20集
        if(payIdList.size() > 10 && payIdList.size() <= 20) {
            Map<String, Object> map = new HashMap<>();
            int count = payIdList.size();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
            map.put("name", "后"+count+"集");
            map.put("price", price);
            map.put("trackCount", count);
            list.add(map);
        }
        if(payIdList.size() > 20) {
            Map<String, Object> map = new HashMap<>();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(20));
            map.put("name", "后20集");
            map.put("price", price);
            map.put("trackCount", 20);
            list.add(map);
        }

        //后30集
        if(payIdList.size() > 20 && payIdList.size() <= 30) {
            Map<String, Object> map = new HashMap<>();
            int count = payIdList.size();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
            map.put("name", "后"+count+"集");
            map.put("price", price);
            map.put("trackCount", count);
            list.add(map);
        }
        if(payIdList.size() > 30) {
            Map<String, Object> map = new HashMap<>();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(30));
            map.put("name", "后30集");
            map.put("price", price);
            map.put("trackCount", 30);
            list.add(map);
        }

        //后50集
        if(payIdList.size() > 30 && payIdList.size() <= 50) {
            Map<String, Object> map = new HashMap<>();
            int count = payIdList.size();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
            map.put("name", "后"+count+"集");
            map.put("price", price);
            map.put("trackCount", count);
            list.add(map);
        }
        // 最多购买50集;
        if(payIdList.size() > 50) {
            Map<String, Object> map = new HashMap<>();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(50));
            map.put("name", "后50集");
            map.put("price", price);
            map.put("trackCount", 50);
            list.add(map);
        }
        return list;
    }

    @Override
    public List<TrackInfo> findPaidTrackInfoList(Long trackId, Integer trackCount) {
        //跟据声音Id获取声音对象
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        Assert.notNull(trackInfo, "声音对象不为空！");

        //获取已支付的声音列表
        Result<List<Long>> userPaidTrackIdList = userInfoFeignClient.findUserPaidTrackIdList(trackInfo.getAlbumId());
        Assert.notNull(userPaidTrackIdList, "已支付声音列表结果集不为空！");
        List<Long> paidTrackIdList = userPaidTrackIdList.getData();
        Assert.notNull(paidTrackIdList, "已支付声音列表不为空！");

        //声明一个声音对象集合
        List<TrackInfo> paidTrackInfoList = new ArrayList<>();
        if(trackCount>0){
            //构建查询条件
            LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TrackInfo::getAlbumId, trackInfo.getAlbumId())
                    .gt(TrackInfo::getOrderNum, trackInfo.getOrderNum())
                    .orderByAsc(TrackInfo::getOrderNum);
            if(!CollectionUtils.isEmpty(paidTrackIdList)){
                wrapper.notIn(TrackInfo::getId, paidTrackIdList);
            }
            wrapper.last("limit " + trackCount);
           paidTrackInfoList = this.list(wrapper);
        }
        return paidTrackInfoList;
    }
}
